using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

namespace XnaDevRu.Bullet
{
	/// <summary>
	/// PHY_ScalarType enumerates possible scalar types.
	/// See the StridingMeshInterface for its use
	/// </summary>
	public enum PHY_ScalarType
	{
		PHY_FLOAT,
		PHY_DOUBLE,
		PHY_INTEGER,
		PHY_SHORT,
		PHY_FIXEDPOINT88
	}

	/// <summary>
	/// StridingMeshInterface is the interface class for high performance access to triangle meshes
	/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
	/// </summary>
	public abstract class StridingMeshInterface
	{
		protected Vector3 m_scaling;

		public StridingMeshInterface()
		{
			m_scaling=new Vector3(1f,1f,1f);
		}

		public void InternalProcessAllTriangles(InternalTriangleIndexCallback callback, Vector3 aabbMin, Vector3 aabbMax)
		{
			//int numtotalphysicsverts = 0;
			//int part, graphicssubparts = getNumSubParts();
			//char* vertexbase;
			//char* indexbase;
			//int indexstride;
			//PHY_ScalarType type;
			//PHY_ScalarType gfxindextype;
			//int stride, numverts, numtriangles;
			//int gfxindex;
			//Vector3[] triangle = new Vector3[3];
			//float* graphicsbase;

			//Vector3 meshScaling = getScaling();

			/////if the number of parts is big, the performance might drop due to the innerloop switch on indextype
			//for (part = 0; part < graphicssubparts; part++)
			//{
			//    getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
			//    numtotalphysicsverts += numtriangles * 3; //upper bound

			//    switch (gfxindextype)
			//    {
			//        case PHY_INTEGER:
			//            {
			//                for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
			//                {
			//                    int* tri_indices = (int*)(indexbase + gfxindex * indexstride);
			//                    graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
			//                    triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
			//                    triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
			//                    triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    callback->internalProcessTriangleIndex(triangle, part, gfxindex);
			//                }
			//                break;
			//            }
			//        case PHY_SHORT:
			//            {
			//                for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
			//                {
			//                    short* tri_indices = (short*)(indexbase + gfxindex * indexstride);
			//                    graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
			//                    triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
			//                    triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
			//                    triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
			//                    callback->internalProcessTriangleIndex(triangle, part, gfxindex);
			//                }
			//                break;
			//            }
			//        default:
			//            ASSERT((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
			//    }
			//    unLockReadOnlyVertexBase(part);
			//}
		}


		/// get read and write access to a subpart of a triangle mesh
		/// this subpart has a continuous array of vertices and indices
		/// in this way the mesh can be handled as chunks of memory with striding
		/// very similar to OpenGL vertexarray support
		/// make a call to unLockVertexBase when the read and write access is finished	
		//public abstract void getLockedVertexIndexBase(char **vertexbase, int numverts,PHY_ScalarType type, int stride,char **indexbase,int indexstride,int numfaces,PHY_ScalarType indicestype,int subpart=0);
		
		//public abstract void getLockedReadOnlyVertexIndexBase(char **vertexbase, int numverts,PHY_ScalarType type, int stride, char **indexbase,int indexstride,int numfaces,PHY_ScalarType indicestype,int subpart=0);
	
		/// unLockVertexBase finishes the access to a subpart of the triangle mesh
		/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
		public abstract void unLockVertexBase(int subpart);

		public abstract void unLockReadOnlyVertexBase(int subpart);


		/// getNumSubParts returns the number of seperate subparts
		/// each subpart has a continuous array of vertices and indices
		public abstract int getNumSubParts();

		public abstract void preallocateVertices(int numverts);
		public abstract void preallocateIndices(int numindices);

		public Vector3 getScaling()  {
			return m_scaling;
		}

		public void setScaling(Vector3 scaling)
		{
			m_scaling = scaling;
		}
	}
}
